
#include "define.h"

int main()
{
	
/////////////////////////////////////////////
//Add by wangyd, for correcting dpram error	
	asm("set 0x40000000, %g1");
//	asm("ld	[ %g1 + 4 ], %i7");
	asm("ld	[ %g1 ], %fp");
	asm("add	%fp, -144, %sp");
	asm("nop");
	
/////////////////////////////////////////////
		
	struct gpt_regs *gpt_r = (struct gpt_regs *) GPT_ADD;
	struct gpio_regs *gpio_r = (struct gpio_regs *) GPIO_ADD;
	struct uart_regs *uart_r = (struct uart_regs *) UART_ADD;
	struct irq_regs *irq_r = (struct irq_regs *) IRQ_ADD;
	
	volatile unsigned int *ip_ld = (int *) IPLD_ADD;
	volatile unsigned int *syw = (int *) SYW_ADD;
	volatile unsigned int *bit22 = (int *) BIT22_ADD;
	volatile unsigned int *bit23 = (int *) BIT23_ADD;
	volatile unsigned int *userID = (int *) UID_ADD;
	volatile unsigned int *mn = (int *) M_ADD;
	volatile unsigned int *e2_data = (int *) E2_ADD;
	volatile unsigned int *d0_data = (int *) D0_ADD;
	volatile unsigned int *d1_data = (int *) D1_ADD;
	
	
	volatile unsigned int *temp_data = (int *) TEMP_ADD;

	int i;
	int state, func_num, gl_num, unit_num, wcnt;
	int uart_wuid;
	int GPIO13, GPIO14, GPIO14_last;
	int comp_addr, comp_length, comp_length_left, comp_checkout, comp_checkout_c, comp_offset;
	
	
///////////////////////////////
//initialization
	*ip_ld=0x1;		//load m,n,...

	state = INIT;		//inital state

	irq_r->irqmask = 0x00000000;		//disable all interupt

	gpio_r->dir = 0x000080FE;		//GPIO[0]:input, GPIO[1~7]:output, GPIO[8~14]:input, GPIO{15]:output
	gpio_r->dout = 0x00008000;		//GPIO[15] = 1
	gpio_r->imask = 0x00000001;		//enable interupt of GPIO[0]
	gpio_r->ipol = 0x00000000;		//falling edge interupt
	gpio_r->iedge = 0xFFFFFFFF;		//edge triggered
	
	uart_r->scaler = 0x00000104;		//brate: 9600 20M:104,10M:82
	uart_r->control = 0x00000037;		//enable T&R, enable r interupt, enable odd parity generate&check
	
	gpt_r->scalerload = 0x000000FF;		//timer pre-scaler
	gpt_r->reload = 0xFFFFFFFF;		//timer1 scaler
	gpt_r->control = 0x00000007;		//enable timer, disable interupt
	
	irq_r->irqmask = 0;//0x00000008;		//enable gpio interupt
	
	GPIO14 = 1;
	GPIO14_last = 1;


////////////////////////////////////
//main loop
	i = 1; 
	while( i==1 )
	{
		//watch dog
		if( (gpt_r->counter) <= COUNTER_TH )
		{
			gpt_r->control = 0x00000007;		//reset timer
			gpio_r->dout = (gpio_r->dout) & 0xFFFF7FFF;		//GPIO[15]=0
			gpio_r->dout = (gpio_r->dout) | 0x00008000;		//GPIO[15]=1
//			gpio_r->dout = (gpio_r->dout) ^ 0x00008000;
		}
		//end watch dog
		
		GPIO14_last = GPIO14;
		GPIO14 = (gpio_r->din >> 14) & 0x00000001;		//GPIO14
		
		//uart program
		if( state == UART_WE2 )		//write E2, for function 2
		{
			if( wcnt == -2)
			{
				*userID = uart_wuid;	//write user ID to E2
				wcnt = -1;
			}
			else if( wcnt == -1 )
			{
				if( *userID == uart_wuid )		//wait for E2 write done
				{
					mn[0] = temp_data[0];		//write M0 to E2
					wcnt = 0;
				}
			}
			else if( wcnt < 31 )
			{
				if( mn[wcnt] == temp_data[wcnt] )		//wait for E2 write done
				{
					wcnt++;
					mn[wcnt] = temp_data[wcnt];		//write M/N to E2
				}
			}
			else if( wcnt == 31 )
			{
				if( mn[31] == temp_data[31] )		//wait for E2 write done
					state = INIT;		//function 2 done
			}
		}
		else if( state == UART_T4 )
		{
			if( wcnt < 32 )
			{
				//sent SYW1~8, Bit20~73
				while( (uart_r->status & 0x00000080 ) == 0x0) ;	//wait until fifo is half-empty
				uart_r->data = syw[wcnt] >> 8;
				while( (uart_r->status & 0x00000080 ) == 0x0) ;	//wait until fifo is half-empty
				uart_r->data = syw[wcnt] & 0x000000FF;
				wcnt++;
				
				while( (uart_r->status & 0x00000080 ) == 0x0) ;	//wait until fifo is half-empty
				uart_r->data = syw[wcnt] >> 8;
				while( (uart_r->status & 0x00000080 ) == 0x0) ;	//wait until fifo is half-empty
				uart_r->data = syw[wcnt] & 0x000000FF;
				wcnt++;
			}
			else if( wcnt == 32 )
			{
				while( (uart_r->status & 0x00000080 ) == 0x0) ;	//wait until fifo is half-empty
				uart_r->data = 0x00;		//transmit 0x00
				while( (uart_r->status & 0x00000080 ) == 0x0) ;	//wait until fifo is half-empty
				uart_r->data = 0x00;		//transmit 0x00
				while( (uart_r->status & 0x00000080 ) == 0x0) ;	//wait until fifo is half-empty
				uart_r->data = 0xEE;		//transmit 0xEE
				while( (uart_r->status & 0x00000004 ) == 0x0) ;	//wait until all data is sent
				gpio_r->dout = gpio_r->dout & 0xFFFFFFFD;		//GPIO[1] = 0
				state = INIT;		//function 4 done
			}
		}
		else if( (uart_r->status & 0x00000001) == 0x00000001 )		//uart received data
		{
			if( state == INIT )
			{
				 if( uart_r->data == 0x0000005A )
				 	state = UART_R0;		//received 0th byte 0x5A
			}
			else if( state == UART_R0 )
			{
				if( uart_r->data == 0x000000A5 )
				 	state = UART_R1;		//received 1st byte 0xA5
				else
					state = INIT;		//not received 0xA5, back to initial state
			}
			else if( state == UART_R1 )
			{
				func_num= (uart_r->data) >> 3;		//store function number
				state = UART_R2;		//received 2nd byte
			}
			else if( state == UART_R2 )
			{
				gl_num = uart_r->data;		//store group line number(not used)
				state = UART_R3;		//received 3rd byte
			}
			else if( state == UART_R3)
			{
				unit_num = ((gpio_r->din) >> 8) & 0x0000001F;	//GPIO[8-12]
				if( (unit_num) == (uart_r->data) )	//unit number match
				{
					if( func_num == 0x00000001 )	//function 1: system inquiry
						state = UART_F1;
					else if( func_num == 0x00000002 )	//function 2: system write
					{
						wcnt = -2;		//initial write counter
						state = UART_F2;
					}
					else if( func_num == 0x00000010 )	//function 3: system self-check 1
						state = UART_F3;
					else if( func_num == 0x00000011 )	//function 4: system self-check 2
						state = UART_F4;
					else
						state = INIT;		//bad function number
				}
				else
					state = INIT;		//unit number unmatch
			}
			else if( state == UART_F1 )		//function 1
			{
				if( uart_r->data == 0x000000F5 )		//received 0xF5
				{
					gpio_r->dout = gpio_r->dout | 0x00000002;	//GPIO[1] = 1
					uart_r->data = 0x00000055;		//transmit 0x55
					uart_r->data = unit_num;		//transmit unit number
					uart_r->data = (*userID) >> 8;
					uart_r->data = (*userID) & 0x000000FF;
					while( (uart_r->status & 0x00000080 ) == 0x0) ;	//wait until fifo is half-empty
					uart_r->data = 0x000000EE;	//transmit 0xEE
					while( (uart_r->status & 0x00000004 ) == 0x0) ;	//wait until all data is sent
					gpio_r->dout = gpio_r->dout & 0xFFFFFFFD;	//GPIO[1] = 0
				}
				state = INIT;		//function 1 done
			}
			else if( state == UART_F2 )		//function 2
			{
				if(wcnt == -2)
				{
					uart_wuid = (uart_r->data) << 8;
					wcnt = -1;
				}
				else if(wcnt == -1)
				{
					uart_wuid = uart_wuid | (uart_r->data);
					wcnt = 0;
				}
				else if( wcnt < 64 )
				{
					if( (wcnt)%2 == 0)
						temp_data[wcnt/2] = (uart_r->data) << 8;		//store high byte of one half-word
					else
						temp_data[wcnt/2] = temp_data[wcnt/2] | (uart_r->data);		//store low byte of one half-word
					wcnt++;
				}
				else if( uart_r->data == 0x000000F5 )
				{
					wcnt = -2;
					state = UART_WE2;		//write E2
					//state = INIT;		//function 2 done
				}
				else
					state = INIT;		//bad uart received data
			}
			else if( state == UART_F3 )		//function 3
			{
				if( uart_r->data == 0x000000F5 )		//received 0xF5
				{
					gpio_r->dout = gpio_r->dout | 0x00000002;		//GPIO[1] = 1
					uart_r->data = 0x00000055;		//transmit 0x55
					uart_r->data = 0x00000050;		//transmit 0x50
					uart_r->data = (*bit22) >> 8;
					uart_r->data = (*bit22) & 0x000000FF;
					while( (uart_r->status & 0x00000080 ) == 0x0) ;	//wait until fifo is half-empty
					uart_r->data = (*bit23) >> 8;
					while( (uart_r->status & 0x00000080 ) == 0x0) ;	//wait until fifo is half-empty
					uart_r->data = 0x000000EE;		//transmit 0xEE
					while( (uart_r->status & 0x00000004 ) == 0x0) ;	//wait until all data is sent
					gpio_r->dout = gpio_r->dout & 0xFFFFFFFD;		//GPIO[1] = 0
				}
				state = INIT;		//function 3 done
			}
			else if( state == UART_F4 )		//function 4
			{
				if( uart_r->data == 0x000000F5 )
				{
					gpio_r->dout = gpio_r->dout | 0x00000002;		//GPIO[1] = 1
					uart_r->data = 0x00000055;		//transmit 0x55
					state = UART_T4;		//transmit data
					wcnt = 0;
				}
				else
					state = INIT;		//bad received data
			}
			else
				state = INIT;
		}
		//end uart program
		
		//gpio_program
		else if( state == GPIO_D )		//All data has been received, compute the checkout
		{
			comp_checkout_c=0x0;
			for(i=0; i<((comp_length)/2); i++)
			{
				comp_checkout_c += ((temp_data[i] & 0x000000FF) + ((temp_data[i] >> 8) & 0x000000FF));		//compute checkout
			}
			comp_checkout_c = comp_checkout_c & 0x000000FF;	//low 8 bit of checkout
			if ( comp_checkout_c == comp_checkout )	//check if the chechout is right
			{
				wcnt = -1;
				state = GPIO_C;		//check out correct, start compensation
			}
			else
				state = INIT;		//check out incorrect
		}
		else if( state == GPIO_C )		//store data into E2
		{
			if ( wcnt == -1 )		//first data
			{
				e2_data[comp_addr] = temp_data[0];
				wcnt++;
			}
			else if(wcnt < (comp_length/2))		//store rest data
			{
				if( e2_data[comp_addr+wcnt] == temp_data[wcnt] )		//if data is stored
				{
					wcnt++;
					e2_data[comp_addr+wcnt] = temp_data[wcnt];	//Store data into E2
				}
			}
			else if(wcnt == comp_length/2)
				state = INIT;		//compensation done
		}
		else if( GPIO14 == 0 && GPIO14_last == 1 )
		{
		
			GPIO13 = ((gpio_r->din) >> 13) & 0x00000001;	//GPIO[13]

			if(state == INIT && GPIO13 == 1)	//Receive Header
			{
				if( d0_data[3] == 0xA8A8 && d1_data[3] == 0xA8A8 )		//Head info
				{
					if( d1_data[1] == *userID )		//userID match
					{
						state = GPIO_H;		//received header
						comp_addr = d0_data[1];		//Store the compensation address
						comp_length = d0_data[2];		//Store the compensation data length
						comp_length_left = d0_data[2] >> 1;		//Store the compensation data length left(unit: 16bits)
						comp_checkout = d0_data[0];
						comp_offset = 0x0;		//initial address offset
					}
				}
			}
			else if(state == GPIO_H && GPIO13 == 0)		//Receive compensation data
			{
				if( comp_length_left <= 4 )		//less than 4 half-word left
				{
					for(i=comp_length_left; i>0; i--)
					{
						temp_data[comp_offset+comp_length_left-i] = d0_data[3-comp_length_left+i];		//Store compensation data
					}
					state = GPIO_D;		//All data has received
				}
				else if( comp_length_left > 4 && comp_length_left <= 8 )		//less than 8 half-word left
				{
					for(i=4; i>0; i--)
					{
						temp_data[comp_offset+4-i] = d0_data[i-1];	//Store the data
					}
					comp_length_left -= 4;
					for(i=comp_length_left; i>0; i--)
					{
						temp_data[comp_offset+4+comp_length_left-i] = d1_data[3-(comp_length_left-i)];	//Store the data
					}
					state = GPIO_D;	//All data has received
				}
				else if( comp_length_left > 8 )
				{
					for(i=4; i>0; i--)
					{
						temp_data[comp_offset+(4-i)] = d0_data[i-1];	//Store the data
					}
					for(i=4; i>0; i--)
					{
						temp_data[comp_offset+(8-i)] = d1_data[i-1];	//Store the data
					}
					comp_offset = comp_offset + 8;	//Next addr
					comp_length_left = comp_length_left - 8;	//data left
				}
			}
			else
				state = INIT;		//bad GPIO14 interupt
		}
		//end GPIO14 program
		
		i = 1;	
	}
	//end main loop
	
	return 0;
}
